﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using ImageManipulation;
using System.Text.RegularExpressions;

namespace Cms.EntLib
{
    public class CssBackground{
        public string CssName { get; set; }
        public int ImgWidth { get; set; }
        public int ImgHeight { get; set; }
        public int x { get; set; }
        public int y { get; set; }
    }
    public class ImageMerge
    {
        private int ImgWidth = 16;
        private int ImgHeight=16;
        private byte[] saveImg = null;
        private FileInfo[] fileInfo;
        private bool saveToFile;
        private string saveFilePath;
        private List<CssBackground> listCss = new List<CssBackground>();
        /// <summary>
        /// 合并图片
        /// </summary>
        /// <param name="_fileInfo"></param>
        /// <param name="imgWidth"></param>
        /// <param name="imgHeight"></param>
        /// <param name="_saveToImg"></param>
        /// <param name="_saveFilePath"></param>
        public ImageMerge(FileInfo[] _fileInfo,int imgWidth,int imgHeight,bool _saveToImg,string _saveFilePath)
        {
            this.saveToFile = _saveToImg;
            this.saveFilePath = _saveFilePath;
            this.fileInfo = _fileInfo;
            this.ImgWidth = imgWidth;
            this.ImgHeight =ImgHeight ;
            List<CssBackground> listCss = new List<CssBackground>();
        }
        /// <summary>
        /// 图片合并(保存文件)
        /// </summary>
        /// <param name="_fileInfo"></param>
        /// <param name="imgWidth"></param>
        /// <param name="imgHeight"></param>
        /// <param name="_saveFilePath"></param>
        public ImageMerge(FileInfo[] _fileInfo,int imgWidth,int imgHeight,string _saveFilePath):this(_fileInfo,imgWidth,imgHeight,true,_saveFilePath)
        { 
            
        }
        /// <summary>
        /// 图片合并(输出流)
        /// </summary>
        /// <param name="_fileInfo"></param>
        /// <param name="imgWidth"></param>
        /// <param name="imgHeight"></param>
        public ImageMerge(FileInfo[] _fileInfo, int imgWidth, int imgHeight) : this(_fileInfo, imgWidth, imgHeight, false, "") { }
        public ImageMerge(string DirectoryName, int imgWidth, int imgHeight, bool _saveToImg, string _saveFilePath) :
            this(new DirectoryInfo(DirectoryName).GetFiles(), imgWidth, imgHeight, _saveToImg, _saveFilePath) { 
            
        }
        /// <summary>
        /// 生成合成图
        /// </summary>
        /// <param name="fileInfo"></param>
        public bool CreateSprite()
        {
            bool result = true;
            int size = this.ImgHeight;
            //byte[] result = null;
            System.IO.FileInfo[] fis = fileInfo;//di.GetFiles();
            Size ImgSize = new Size(this.ImgWidth, size * fis.Length);
            Color bgColor = Color.Transparent;
            using (Bitmap bigImg = new Bitmap(ImgSize.Width, ImgSize.Height))
            {
                string imgType = "png";
                ImageFormat format = ImageFormat.Png;
                switch (imgType)
                {
                    case "jpeg":
                        format = ImageFormat.Jpeg;
                        break;
                    case "jpg":
                        format = ImageFormat.Jpeg;
                        break;
                    case "gif":
                        format = ImageFormat.Gif;
                        break;
                    default:
                        break;
                }
                using (Graphics g = Graphics.FromImage(bigImg))
                {
                    //设置高质量插值法 
                    g.InterpolationMode = InterpolationMode.High;
                    //设置高质量,低速度呈现平滑度 
                    g.SmoothingMode = SmoothingMode.HighQuality;
                    //清空画布并以透明背景色填充 
                    if (bgColor == Color.Transparent && (format == ImageFormat.Jpeg || format == ImageFormat.Gif))
                        g.Clear(Color.White);
                    else
                        g.Clear(bgColor);
                    int RectX = 0;
                    int RectY = 0;
                    foreach (FileInfo fi in fis)
                    {                        
                        string imgName = Path.GetFileNameWithoutExtension(fi.Name);
                        Image img = Image.FromFile(fi.FullName);
                        g.DrawImage(img, RectX, RectY, img.Size.Width, img.Size.Height);                        
                        //生成样式
                        CssBackground cssModel = new CssBackground();
                        if (EntLib.TypeParse.IsNumeric(imgName))
                        {
                            imgName = "icon_" + imgName;
                        }
                        cssModel.CssName = imgName;
                        cssModel.x = 0;
                        cssModel.y = RectY;
                        cssModel.ImgWidth = img.Size.Width;
                        cssModel.ImgHeight = img.Size.Height;
                        RectY = RectY + img.Size.Height;
                        this.listCss.Add(cssModel);
                    }
                }
                using (MemoryStream ImgStream = new MemoryStream())
                {
                    if (saveToFile && File.Exists(saveFilePath))
                    {
                        try
                        {
                            File.Delete(saveFilePath);
                        }
                        catch(Exception e){
                            EntLib.LogHelper.GetInstance().Error(e);
                        }
                    }
                    if (format == ImageFormat.Gif)
                    {
                        OctreeQuantizer quantizer = new OctreeQuantizer(255, 8);
                        using (Bitmap quantized = quantizer.Quantize(bigImg))
                        {
                            if (saveToFile)
                                quantized.Save(saveFilePath, format);
                            else
                                quantized.Save(ImgStream, format);
                        }
                    }
                    else
                    {
                        if (saveToFile)
                        {
                            try
                            {
                                bigImg.Save(saveFilePath, format);
                            }
                            catch (Exception e) {
                                //throw;
                                result = false;
                            }
                        }
                        else
                            bigImg.Save(ImgStream, format);
                    }
                    if (saveToFile)
                        saveImg = ImgStream.ToArray();
                }
            }
            return true;
        }

        /// <summary>
        /// 输出为流
        /// </summary>
        /// <returns></returns>
        public byte[] OutputToStream() {
            return this.saveImg;
        }
        
        /// <summary>
        /// 构造CSS
        /// </summary>
        /// <returns></returns>
        public string BuilderCss(string partten,string spriteFileName) {
            StringBuilder sb = new StringBuilder();
            string prepartten = partten;
            Regex regex = new Regex("\\}[a-zA-Z_\\d]+,");
            prepartten=regex.Replace(prepartten, "},");
            sb.AppendFormat(prepartten, "");
            sb.Append("{");
            sb.AppendFormat("background-image:url(\"{0}\");display:inline-block;", spriteFileName);
            sb.AppendFormat("width:{0}px;height:{1}px;", listCss[0].ImgWidth, listCss[0].ImgHeight);
            sb.Append("background-position:16px 16px;");
            sb.AppendLine("}");
            foreach (CssBackground model in listCss) {
                sb.AppendFormat(partten, "."+model.CssName);
                sb.Append("{");
                //sb.AppendFormat("background-image:url(\"{0}\");display:inline-block;", spriteFileName);
                //sb.AppendFormat("width:{0}px;height:{1}px;", model.ImgWidth, model.ImgHeight);
                sb.AppendFormat("background-position:0px -{0}px;", model.y);
                sb.AppendLine("}");      
            }
            return sb.ToString();
        }
    }
}
